package com.hsogoo.ultraman.monitor;

import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import com.hsogoo.ultraman.Constant;
import com.hsogoo.ultraman.constants.PropertySourceConstants;
import com.hsogoo.ultraman.container.ConfigContainer;
import com.hsogoo.ultraman.listener.ConfigServerChangeListener;
import com.hsogoo.ultraman.listener.RemoteConfigChangeListener;
import com.hsogoo.ultraman.repository.RemoteConfigRepository;
import com.hsogoo.ultraman.util.AppendUtil;
import com.hsogoo.ultraman.utils.ConfigMetaUtil;

import java.util.List;
import java.util.Map;

import lombok.extern.slf4j.Slf4j;

/**
 * Created by za-huangsaigang on 2018/9/21.
 */
@Slf4j
public class ConfigChangeMonitor implements RemoteConfigChangeListener {

    private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults();
    private ConfigMetaUtil configMetaUtil;
    private ZkClient zkClient;
    private Map<String, RemoteConfigRepository> remoteConfigRepositories = Maps.newConcurrentMap();

    public ConfigChangeMonitor(){
        configMetaUtil = ConfigContainer.getBean(ConfigMetaUtil.class);
        zkClient = ZkClient.getInstance(configMetaUtil.getRegistryUrl());
        //监听zk端配置的变化
        initMonitorRemoteConfigChange();
    }

    private void initMonitorRemoteConfigChange(){
        List<String> namespaces = NAMESPACE_SPLITTER.splitToList(PropertySourceConstants.ULTRAMAN_DEFAULT_NAMESPACES);
        for(String namespace : namespaces){
            zkClient.watchWithChild(assembleWatchPath(namespace), this);
        }
    }

    private String assembleWatchPath(String namespace){
        String appName = configMetaUtil.getAppName();
        String envName = configMetaUtil.getEnvName();
        String path = AppendUtil.appendString(Constant.CONFIG_PUBLISH_NODE,Constant.PATH_PREFIX, envName,
                Constant.PATH_PREFIX, appName, Constant.PATH_PREFIX, namespace);
        return path;
    }

    public void monitorConfigServer(ConfigServerChangeListener configServerChangeListener){
        zkClient.watchServerList(Constant.CONFIG_SERVER_LIST, configServerChangeListener);
    }

    public List<String> getAllConfigServer(){
        return zkClient.getAllServer();
    }

    public void monitorRemoteConfigChange(String namespace, RemoteConfigRepository remoteConfigRepository){

        if(remoteConfigRepositories.containsKey(namespace)){
            return;
        }
        remoteConfigRepositories.put(namespace, remoteConfigRepository);

    }

    @Override
    public void onChange(String namespace) {
        log.info("从zk监听到{}配置发生变化。。。", namespace);
        //从缓存里取namespace对应的RemoteConfigRepository取更新对应的配置
        if(remoteConfigRepositories.containsKey(namespace)){
            RemoteConfigRepository remoteConfigRepository = remoteConfigRepositories.get(namespace);
            remoteConfigRepository.updateNamespaceRemoteConfig();
        }
    }
}
